#include <windows.h>
#include <stdio.h>

#define state_def	0
#define state_proc	1
#define state_bcode	2
#define state_acode	3

char * ltrim(char*c){
	while(c[0] && (c[0]==' ' || c[0]=='\t'))c++;
	return c;
}

int is_go(char*c){
	int i=0;
	//skip spaces
	while( c[i]!=0 && strchr(" \t",c[i])!=NULL) i++;
	if(strnicmp(c+i,"go",2))return 0;
	i+=2;
	while( c[i]!=0 ){if( !strchr(" \t\r\n",c[i]) )return 0;i++;}
	return 1;
}


int fmove(FILE*dst,FILE**src){
	int ret=0;
	char buf[1024];
	fflush(src[0]);
	rewind(src[0]);
	while( fgets(buf, sizeof(buf), src[0]) ){
		fputs(buf,dst);
		ret=1;
	}
	fclose(src[0]);
	src[0]=tmpfile();
	if(!src[0]){printf("error creating tmp file\n");exit(1);}
	return ret;
}

int main(int argc, char*argv[]){
	char buf[4096];
	int	state=state_def;
	printf("Parsing procedures comments for \"*CODE Before:\" and \"*CODE After:\"\n");
	FILE*fin=fopen(argv[1],"rb");
	if(!fin){printf("can't open input file (parameter 1)");return 1;}
	FILE*fout=fopen(argv[2],"wb");
	if(!fin){printf("can't create output file (parameter 2)");return 1;}
	FILE*ftmph=tmpfile();
	if(!ftmph){printf("can't create header tmp file");return 1;}
	FILE*ftmpb=tmpfile();
	if(!ftmpb){printf("can't create body tmp file");return 1;}
	FILE*ftmpf=tmpfile();
	if(!ftmpf){printf("can't create footer tmp file");return 1;}

	while(fgets(buf,sizeof(buf),fin)){
		switch(state){
			case state_def:{
				if(!strnicmp(ltrim(buf),"create proc",11)){
					state=state_proc;
					fputs(buf,ftmpb);
				}else{
					fputs(buf,fout);
				}
				break;
			}
			case state_proc:{
				if( is_go(buf) ){
					state=state_def;
					if(fmove(fout,&ftmph))fputs("go\n",fout);
					if(fmove(fout,&ftmpb))fputs("go\n",fout);
					if(fmove(fout,&ftmpf))fputs("go\n",fout);
				}else if( !strnicmp(buf,"*CODE Before:",13) ){
					fputs(buf,ftmpb);
					state=state_bcode;
				}else if( !strnicmp(buf,"*CODE After:",12) ){
					fputs(buf,ftmpb);
					state=state_acode;
				}else{
					fputs(buf,ftmpb);
				}
				break;
			}
			case state_bcode:{
				if( buf[0]=='*' ){
					fputs(buf,ftmpb);
					if( !strnicmp(buf,"*CODE After:",12) ){
						state=state_acode;
					}else{
						state=state_proc;
					}
				}else{
					fputs(buf,ftmph);
					fputs(buf,ftmpb);
				}
				break;
			}
			case state_acode:{
				if( buf[0]=='*' ){
					fputs(buf,ftmpb);
					state=state_proc;
				}else{
					fputs(buf,ftmpf);
					fputs(buf,ftmpb);
				}
				break;
			}
		}
	}
	fflush(fout);
	fclose(fout);
	fclose(ftmph);
	fclose(ftmpb);
	fclose(ftmpf);
	fclose(fin);
	return 0;
}
